/**
 * @file      ac_tlm_card.cpp
 * @author    Bruno de Carvalho Albertini
 * 
 * @author    The ArchC Team
 *            http://www.archc.org/
 *
 *            Computer Systems Laboratory (LSC)
 *            IC-UNICAMP
 *            http://www.lsc.ic.unicamp.br/
 * 
 * @version   0.1
 * @date      Sun, 02 Apr 2006 08:07:46 -0200
 * 
 * @brief     Implements a ac_tlm card.
 * 
 * @attention Copyright (C) 2002-2005 --- The ArchC Team
 * 
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 * 
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 * 
 * 
 */

//////////////////////////////////////////////////////////////////////////////
// Standard includes
// SystemC includes
// ArchC includes

#include "ac_tlm_card.h"

//////////////////////////////////////////////////////////////////////////////

/// Namespace to isolate card from ArchC
using user::ac_tlm_card;

/// Constructor
ac_tlm_card::ac_tlm_card( sc_module_name module_name ) :
  sc_module( module_name ),
  target_export("iport")
{
  /// Binds target_export to the card
  target_export( *this );

  if( !(eleitores = fopen(ARQ_ELEITORES, "r+")) ) {
    printf("Erro ao abrir arquivo de eleitores");
    exit(1);
  }
  if( !(candidatos = fopen(ARQ_CANDIDATOS, "r+")) ) {
    printf("Erro ao abrir arquivo de candidatos");
    exit(1);
  }
  if( !(partidos = fopen(ARQ_PARTIDOS, "r+")) ) {
    printf("Erro ao abrir arquivo de partidos");
    exit(1);
  }
  if( !(mesarios = fopen(ARQ_MESARIOS, "r")) ) {
    printf("Erro ao abrir arquivo de mesários");
    exit(1);
  }

}

/// Destructor
ac_tlm_card::~ac_tlm_card() {

  fclose(eleitores);
  fclose(candidatos);
  fclose(partidos);
  fclose(mesarios);

}

/** Internal Write
 * Note: Always write 32 bits
 * @param a is the address to write
 * @param d id the data being write
 * @returns A TLM response packet with SUCCESS
 */
ac_tlm_rsp_status ac_tlm_card::writec( const uint32_t &a , const uint32_t &d )
{
  FILE *arq;
  int offset;

  if( (a >= END_ELEITORES) && (a < END_CANDIDATOS) ) {
    arq = eleitores;
    offset = a - END_ELEITORES;
  }
  else if( (a >= END_CANDIDATOS) && (a < END_PARTIDOS) ) {
    arq = candidatos;
    offset = a - END_CANDIDATOS;
  }
  else if( (a >= END_PARTIDOS) && (a < END_MESARIOS) ) {
    arq = partidos;
    offset = a - END_PARTIDOS;
  }
  else if( (a >= END_MESARIOS) && (a < END_FIM) ) {
    arq = mesarios;
    offset = a - END_MESARIOS;
  }
  else {
    return ERROR;
  }

  fseek(arq, offset, SEEK_SET);
  if(fwrite(&d, 4, 1, arq) < 1) {
    printf("Erro ao escrever no cartão de memória.");
    return ERROR;
  }

  return SUCCESS;
}

/** Internal Read
 * Note: Always read 32 bits
 * @param a is the address to read
 * @param d id the data that will be read
 * @returns A TLM response packet with SUCCESS and a modified d
 */
ac_tlm_rsp_status ac_tlm_card::readc( const uint32_t &a , uint32_t &d )
{
  FILE *arq;
  int offset;

  if( (a >= END_ELEITORES) && (a < END_CANDIDATOS) ) {
    arq = eleitores;
    offset = a - END_ELEITORES;
  }
  else if( (a >= END_CANDIDATOS) && (a < END_PARTIDOS) ) {
    arq = candidatos;
    offset = a - END_CANDIDATOS;
  }
  else if( (a >= END_PARTIDOS) && (a < END_MESARIOS) ) {
    arq = partidos;
    offset = a - END_PARTIDOS;
  }
  else if( (a >= END_MESARIOS) && (a < END_FIM) ) {
    arq = mesarios;
    offset = a - END_MESARIOS;
  }
  else {
    return ERROR;
  }

  fseek(arq, 0, SEEK_END);
  if(offset >= ftell(arq)) {
    (((uint8_t*)&d)[0]) = '\n';
    (((uint8_t*)&d)[1]) = '\n';
    (((uint8_t*)&d)[2]) = '\n';
    (((uint8_t*)&d)[3]) = '\n';
  }
  else {
    fseek(arq, offset, SEEK_SET);
    fread(&d, 4, 1, arq);
  }

  return SUCCESS;
}
